#ifndef COMM_THREAD_H
#define COMM_THREAD_H

#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <list>

template <typename T>
using sptr= std::shared_ptr<T>;

typedef std::string string;

namespace common {

  class ThreadTask {
  public:
    ThreadTask() = default;
    virtual ~ThreadTask() = default;
    virtual void Run() = 0;
  private:

  };

  typedef std::shared_ptr<ThreadTask> ThreadTaskPtr;
  typedef std::function<void()>       OnceTask;

  class Thread
  {
  public:
    Thread() = default;
    explicit Thread(const string& name);
    Thread(OnceTask&& task, bool join = true) : Thread(std::move(task), "", join) {}
    Thread(OnceTask&& task, const string& name, bool join = true);
    virtual ~Thread();

    void Poll();

    void Post(const ThreadTaskPtr& task);

    void Exit();

  private:

    void TaskLoop();

    std::mutex                init_mtx_;
    bool                      init_{false};

    std::mutex                task_mtx_;
    std::list<ThreadTaskPtr>  tasks_;

    sptr<std::thread>         t_;

    std::mutex                take_mtx_;
    std::condition_variable   take_var_;

    bool                      exit_{false};
  };

}

#endif // THREAD_H
